package fun.tan90.device.sink.http.plugin.handler;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.dtflys.forest.Forest;
import com.dtflys.forest.http.ForestRequest;
import com.dtflys.forest.http.ForestRequestType;
import fun.tan90.device.sink.core.SinkHandler;
import fun.tan90.device.sink.core.SinkRule;
import fun.tan90.device.sink.http.plugin.model.SinkHttpRule;
import lombok.extern.slf4j.Slf4j;
import org.noear.snack.ONode;
import org.noear.solon.annotation.Component;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@Slf4j
@Component
public class SinkHttpHandler extends SinkHandler {

    @Override
    public void init(List<ONode> onodeList) {
        for (ONode node : onodeList) {
            String deviceType = node.get("deviceType").getString();
            String dataSource = node.get("dataSource").getString();
            ONode sinkContext = ONode.loadStr(node.get("sinkContext").getString());
            List<SinkHttpRule> sinkRules = sinkContext.ary().stream().map(n -> JSONUtil.toBean(n.toJson(), SinkHttpRule.class)).collect(Collectors.toList());
            SINK_RULES.put(sinkRuleKey(deviceType, dataSource), sinkRules);
        }
    }

    @Override
    public void handle(Map<String, Object> data, Map<String, String> meta, List<? extends SinkRule> sinkRules) {
        for (SinkRule sinkRule : sinkRules) {
            SinkHttpRule sinkHttpRule = (SinkHttpRule) sinkRule;
            String name = sinkHttpRule.getName();
            log.info("sink http name: {}", name);

            ForestRequest<?> forestRequest = Forest.request()
                    .url(sinkHttpRule.getUrl())
                    .setType(ForestRequestType.valueOf(sinkHttpRule.getMethod().toUpperCase()));

            forestRequest
                    .logEnabled(true)
                    .logRequest(true)
                    .logResponseHeaders(true)
                    .logResponseContent(true);

            SinkHttpRule.Timeout timeout = sinkHttpRule.getTimeout();
            forestRequest
                    .readTimeout(timeout.getRead() * 1000)
                    .connectTimeout(timeout.getConnect() * 1000);
            SinkHttpRule.Retry retry = sinkHttpRule.getRetry();
            forestRequest
                    .setRetryEnabled(retry.isEnabled())
                    .maxRetryCount(retry.getRetries())
                    .maxRetryInterval(retry.getInterval() * 1000L);

            String params = sinkHttpRule.getParams();
            if (StrUtil.isNotBlank(params)) {
                params = StrUtil.format(params, data);
                params = StrUtil.format(params, meta);
                ONode nodeParam = ONode.loadStr(params);
                nodeParam.forEach((k, v) -> forestRequest.addQuery(k, v));
            }

            SinkHttpRule.Body body = sinkHttpRule.getBody();
            if (Objects.nonNull(body)) {
                String bodyData = body.getData();
                bodyData = StrUtil.format(bodyData, data);
                bodyData = StrUtil.format(bodyData, meta);
                ONode nodeBodyData = ONode.loadStr(bodyData);
                forestRequest.addBody(nodeBodyData.toJson());
                String type = body.getType();
                forestRequest.setContentType(type);
            }

            String result = forestRequest.executeAsString();
            log.info("sink http result: {}", result);
        }
    }
}
